package com.inspector.app.ui.plot

import android.annotation.SuppressLint
import android.graphics.PointF
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.ObservableParcelable
import androidx.fragment.app.viewModels
import com.inspector.app.databinding.PlotFragBinding
import com.inspector.app.di.persistence.plot.MapItem
import com.inspector.app.di.persistence.plot.MapPoint
import com.inspector.app.di.util.ElevationUtils
import com.inspector.app.di.util.autoCleared
import com.inspector.app.ui.base.BaseDJFragment
import com.inspector.app.ui.widget.NumRangeInputFilter
import com.inspector.app.util.CommonUtil
import com.inspector.app.util.LocationUtils
import com.inspector.app.util.UUIDGenerator
import com.mapsforge.map.EfbGesture
import com.mapsforge.map.EfbGestureListener
import com.mapsforge.map.EfbLatLngPoint
import com.mapsforge.map.EfbLayer
import com.mapsforge.map.EfbMarker
import com.mapsforge.map.EfbMotionEvent
import com.mapsforge.org.oscim.map.IDJMap

/**
 * 标绘页面
 *
 * @author CodeK 2024/7/19
 */
class PlotFragment : BaseDJFragment<PlotFragBinding>() {

    private var mapLifecycleObserver by autoCleared<PlotMapLifecycleObserver>()
    private val viewModel by viewModels<PlotViewModel>()
    private val screenPoint = PointF()
    val dMap: IDJMap get() = mapLifecycleObserver.dMap
    val plotItem = ObservableParcelable<MapItem>()


    override fun provideViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?
    ): PlotFragBinding {
        return PlotFragBinding.inflate(inflater, container, false)
    }

    override fun setupView(view: View, savedInstanceState: Bundle?) {
        initializeMapView() //[加载地图数据]
        observerUI() //[订阅标绘等事件]
    }

    private fun initializeMapView() {
        mapLifecycleObserver = PlotMapLifecycleObserver(this, viewModel)
        lifecycle.addObserver(mapLifecycleObserver)

        //[输入范围校验]
        viewBinding.plotPointBottomSheet.edElevation.filters =
            arrayOf(NumRangeInputFilter(5, 1))

        viewBinding.handler = this
        viewBinding.lifecycleOwner = this
        viewBinding.plotItem = plotItem
        viewBinding.plotMapLifecycleObserver = mapLifecycleObserver
        viewBinding.executePendingBindings()


        mapLifecycleObserver.efbMap.addGestureListener(object : EfbGestureListener {
            override fun onGesture(layer: EfbLayer?, efbGesture: EfbGesture?, event: EfbMotionEvent): Boolean {
                onGesture(event)
                return false
            }

            override fun onItemSingleTapUp(layer: EfbLayer?, efbMarker: EfbMarker?): Boolean {
                return false
            }

            override fun onItemLongPress(layer: EfbLayer?, efbMarker: EfbMarker?): Boolean {
                return false
            }
        })
    }

    private fun observerUI() {
        //[当前标绘类型-控制UI显示隐藏]
        viewModel.drawMode.observe(viewLifecycleOwner) { drawMode ->
            viewBinding.drawMode = drawMode
            viewBinding.executePendingBindings()

            if (drawMode == DrawMode.NONE) { //[退出编辑模式-清空编辑数据]
                viewModel.plotItem.value = null
            }
        }

        //[当前标绘类型-下的标绘数据]
        viewModel.plotItem.observe(viewLifecycleOwner) { item ->
            plotItem.set(item)
            plotItem.notifyChange()
        }
    }

    @SuppressLint("SetTextI18n")
    private fun onGesture(event: EfbMotionEvent) {
        try {
            val drawMode = viewModel.drawMode.value ?: return
            if (drawMode == DrawMode.NONE) return
            screenPoint.set(event.screenPoint)

            if (drawMode == DrawMode.POINT) { //[航点预览]
                val pointF = PointF(
                    viewBinding.plotPoint.tvFlightLineCenter.left.toFloat(),
                    viewBinding.plotPoint.tvFlightLineCenter.top.toFloat()
                )
                val efbLatLngPoint: EfbLatLngPoint = mapLifecycleObserver.efbMap.fromScreenPoint(pointF)
                viewBinding.plotPoint.tvFlightLineLocation.text =
                    LocationUtils.D2Dms(efbLatLngPoint.lng) + "," + LocationUtils.D2Dms(efbLatLngPoint.lat)

                val mapItem = viewModel.plotItem.value ?: MapItem()
                if (viewModel.plotItem.value == null) {
                    val flyElementId = mapItem.flyElementId ?: UUIDGenerator.generate()
                    mapItem.flyElementId = flyElementId
                    mapItem.elementType = 0.toString() //[要素类型，0点，1线，2圆，3多边形，4椭圆]

                    val points = mutableListOf<MapPoint>()
                    points.add(MapPoint().apply {
                        pointId = flyElementId
                        latitude = efbLatLngPoint.lat
                        longitude = efbLatLngPoint.lng
                        latString = LocationUtils.D2Dms(efbLatLngPoint.lat)
                        lngString = LocationUtils.D2Dms(efbLatLngPoint.lng)
                        sort = 0.toString()
                        pointType = 0.toString() //[0点，1线点，2圆心，3多边型点]
                        val offlineElevation =
                            ElevationUtils.getInstance().getOfflineElevation(EfbLatLngPoint(efbLatLngPoint.lat, efbLatLngPoint.lng))
                        elevation = CommonUtil.formatDouble(offlineElevation, 1)
                    })
                    mapItem.points = points
                    mapItem.upload = false
                    mapItem.uploaded = false
                } else {
                    mapItem.points!![0].apply {
                        latitude = efbLatLngPoint.lat
                        longitude = efbLatLngPoint.lng
                        latString = LocationUtils.D2Dms(efbLatLngPoint.lat)
                        lngString = LocationUtils.D2Dms(efbLatLngPoint.lng)
                        val offlineElevation =
                            ElevationUtils.getInstance().getOfflineElevation(EfbLatLngPoint(efbLatLngPoint.lat, efbLatLngPoint.lng))
                        elevation = CommonUtil.formatDouble(offlineElevation, 1)
                    }
                }
                viewModel.plotItem.value = mapItem.copy()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun popBackStack() {
        activity?.finish()
    }


    override fun initData() {}
    override fun initListener() {
    }

}